iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0
Software Development

從Servlet到Spring MVC系列 第 13

Day12 Servlet - Garbled characters

  • 分享至 

  • xImage
  •  

前言

寫這麼久的Web多少都會遇到亂碼的問題,不論是Web頁面的的亂碼、收到Client資訊的亂碼或是連你的log console的曾出現亂嗎,今天我們就來整理這些問題

0、創建module

請參考Day05創建module

一、亂碼原因

簡單說就是編碼與解碼使用不同的字元集,比如說你在編輯文件的時候使用UTF-8編碼,但是在讀取檔案的時候使用BIG5的方式。

二、HTML亂碼

建立Garbled.html

由於intellij會自動的偵測你的charset設定轉換編碼,所以先用nopad++編輯檔案用big5的編碼存檔。
https://ithelp.ithome.com.tw/upload/images/20240927/20128084hdmalngfnE.png

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Garbled</title>
</head>
<body>
哈囉你好~~~
</body>
</html>

Demo

啟動tomcat,訪問Garbled.html
https://ithelp.ithome.com.tw/upload/images/20240927/201280848WJkL3UPki.png

解決

這是因為文件是使用big5進行儲存,瀏覽器是從meta這個tag標籤來決定使用什麼編碼進行decoding,修正後就可以讀到正確的文字了。

Tomcat console亂碼

建立DemoConsoleGarbledServlet

@WebServlet("/DemoConsoleGarbledServlet")
public class DemoConsoleGarbledServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse res){
        System.out.println("訪問DemoConsoleGarbledServlet");
    }
}

Demo

啟動tomcat,訪問DemoConsoleGarbledServlet,查看server console出現亂碼
https://ithelp.ithome.com.tw/upload/images/20240927/20128084hDL34ZO5Ej.png

解決

這是因為java編譯與加載.class檔案時使用的編碼不同,我們可以透過VM option設定D-file.encoding=UTF-8,就可以解決這個問題
https://ithelp.ithome.com.tw/upload/images/20240927/20128084wJ2YhsxONj.png

tomcat logging 編碼設定

相關logging編碼設定檔可以參考Tomcat/conf/logging.properties
https://ithelp.ithome.com.tw/upload/images/20240927/20128084qJnhhrU6vX.png

三、請求亂碼問題-Get

建立RequestFormGet.html

留意meta charset設為big5

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="big5">
    <title>RequestFormGet</title>
</head>
<body>
    <form action="HandleForm" method="get">
        <label for="username">姓名:</label>
        <input type="text" id="username" name="username" required><br><br>
        <input type="submit" value="送出">
    </form>
</body>
</html>

建立HandleFormServlet

@WebServlet("/HandleFormGet")
public class HandleFormServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response){
        System.out.println("=====HandleFormGet=====");
        System.out.println(request.getParameter("username"));
    }
}

Demo

輸入劉德華後送出
https://ithelp.ithome.com.tw/upload/images/20240927/20128084n1pbPNatNH.png
後端log
https://ithelp.ithome.com.tw/upload/images/20240927/20128084p9Xt2ywnXy.png

解決

當我們在meta設置為big5後,送出的get請求會對傳送參數以big5進行URL encode,兒而在tomcat預設是以UTF-8進行解碼,若要修改這個設置,我們可以到下面設定檔進行修改,一般不建議這樣做,html亦維持UTF-8編碼。
https://ithelp.ithome.com.tw/upload/images/20240927/20128084ywOq5BBn29.png
設置如下
https://ithelp.ithome.com.tw/upload/images/20240927/20128084lCfyizVIR2.png

四、請求亂碼問題-Post

建立RequestFormPost.html

html內容同上,修改為Post
HandleFormServlet增加doPost方法

@WebServlet("/HandleForm")
public class HandleFormGetServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("=====HandleFormPost=====");
        //req.setCharacterEncoding("big5");
        System.out.println(req.getParameter("username"));
    }
}

Demo

輸入劉德華後送出
https://ithelp.ithome.com.tw/upload/images/20240927/20128084oZ69tf9zVt.png
後端console
https://ithelp.ithome.com.tw/upload/images/20240927/201280840IWIXYDDPP.png

解決

由於前端使用big5進行request body編碼,但後端使用UTF-8進行解析,故出現亂碼。只要在提取資料前設置request的編碼在提取數據就可以解決該問題。

五、response亂碼問題

建立案例

create DemoResponseGarbledServlet

@WebServlet("/DemoResponseGarbledServlet")
public class DemoResponseGarbledServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //設置response body使用UTF-8進行編碼
        //resp.setCharacterEncoding("UTF-8");
        //告訴client瀏覽器解析的編碼
        //resp.setContentType("text/html;charset=UTF-8");

        resp.getWriter().write("哈囉DemoResponseGarbledServlet~~");
    }
}


https://ithelp.ithome.com.tw/upload/images/20240927/20128084UqjqP3UZef.png

解決

由於瀏覽器收到response訊息時未收到解析編碼的訊息,故用OS預設編碼進行解析,可以透過設定setCharacterEncoding與setContentType來解決此問題。

Reference


上一篇
Day11 Servlet - RequestDispatcher and SendRedirect
下一篇
Day13 Servlet - Absolute and relative path
系列文
從Servlet到Spring MVC36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言